Conversation
TimeProvider.setDiff computes the median client/server clock offset to drive audio/video synchronization, but sorted the offset buffer with a bare Array.prototype.sort(). With no comparator, sort() coerces elements to strings and orders them lexicographically, so the "median" was taken from a wrongly ordered array (e.g. [2, 10, -5, 100] -> [-5, 10, 100, 2]). The resulting offset is unstable and frequently wrong, corrupting every serverTime() calculation and causing playback drift and "Chunk too old, dropping" stalls. Sort numerically with an explicit comparator. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pbtrung
added a commit
to pbtrung/snapweb
that referenced
this pull request
Sep 30, 2026
Ports the fixes from upstream snapcast#165 and snapcast#166 onto the refactored components. Audio: - Sort the clock offsets numerically in TimeProvider.setDiff. A bare sort() ordered them as strings, so the median offset was wrong, which skewed serverTime() and caused drift and dropped chunks - Normalize PCM samples by 2^(bits-1) instead of 2^bits, which played all audio about 6 dB too quiet - Write the UTF-8 byte length into serialized JSON messages instead of the UTF-16 string length, which truncated payloads with non-ASCII characters - Generate the client id with crypto.randomUUID() where available React: - Register the prefers-color-scheme listener once in an effect with cleanup instead of adding a new listener on every render - Use functional updates for the remaining force-update counters - Return 0 instead of NaN for the volume of a group with no clients Cleanup: - Remove no-op clamp expressions in the MediaSession seek handlers - Remove the large commented-out sample server JSON Tests: - Export the message classes and TimeProvider from snapstream.ts and add unit tests for the median, the non-ASCII JSON round trip, Hello and Time messages, and client id generation
pbtrung
added a commit
to pbtrung/snapweb
that referenced
this pull request
Sep 30, 2026
README: - Note the Node.js requirement (20.19+ or 22.12+, from Vite 8) - Add Test and Code style sections covering the unit, coverage and Snapserver integration test commands, Prettier and ESLint - Point out that the prebuilt zip and Debian releases are upstream Snapweb's, since this repository no longer builds Debian packages - Remove the Screenshot and Contributing sections, and the screenshots in docs/images Changelog: - Add the 0.9999 entry: the time sync and audio fixes (including upstream PRs snapcast#165 and snapcast#166), the React and SnapControl fixes, lazy loading and bundle splitting, package updates, tests, Prettier and removed tooling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TimeProvider.setDiff computes the median client/server clock offset to drive audio/video synchronization, but sorted the offset buffer with a bare Array.prototype.sort(). With no comparator, sort() coerces elements to strings and orders them lexicographically, so the "median" was taken from a wrongly ordered array (e.g. [2, 10, -5, 100] -> [-5, 10, 100, 2]).
The resulting offset is unstable and frequently wrong, corrupting every serverTime() calculation and causing playback drift and "Chunk too old, dropping" stalls.
Sort numerically with an explicit comparator.